<!--
 * @Description: 滑动视频组件（算法优化版）
 * @Author: Kerwin
 * @Date: 2024-08-22 14:03:43
 * @LastEditTime: 2025-02-24 17:11:34
 * @LastEditors:  Please set LastEditors
-->
<template>
  <view class="c_container">
    <swiper v-if="displaySwiperList.length" class="swiper" circular :current="current" @change="swiperChange"
      :vertical="true" duration="300">
      <swiper-item class="swiperItem" v-for="(item, index) in displaySwiperList" :key="index" :data-dynamic-id="item.id">
        <view style="z-index: 999">
          <view class="videoCore" :class="{ foled: commentShow && !isPC(), noScale: item.orientation === 0 }">
            <video class="video" :id="item.id.toString()" :autoplay="false" :loop="true"
              :src="getImgFullPath(item?.videoUrl || '')" :poster="getImgFullPath(item.previewImage || '') + ',ar_auto'"
              :controls="controls" :show-fullscreen-btn="true" :show-play-btn="false" :show-center-play-btn="false"
              :object-fit="'contain'" :http-cache="true" preload="auto" @controlstoggle="controlstoggle"
              @fullscreenchange="fullscreenchangeFn" @loadedmetadata="videoLoaded($event, item)" @click="videoPlay(index)"
              @play="onPlay" @pause="onPause" @error="onVideoError"></video>
            <image v-show="!item.isPlay" @click="videoPlay(index)" class="play"
              src="https://image.blacksilverscore.com/uploads/4d06ea54-e6e1-4ebc-9b8c-b629b96bb9d9.png"></image>
          </view>
          <c_sidebar v-if="!props.isPreview" :item="item" :index="index" :isPreview="props.isPreview" :type="props.type"
            @commentHide="commentShow = false" @doLike="doLike" @toShare="toShare" @toComment="toComment"
            @toBusinessCardHome="toBusinessCardHome" @focusAdd="focusAdd"></c_sidebar>
          <view class="footer" :class="{ 'showControl': controls }" id="footer" v-if="!fullScreen">
            <view class="top">
              <view class="name" @click="toBusinessCardHome(item, index)">@{{ item?.user?.nickname }}</view>
              <view class="textBox tit" v-if="item?.name">{{
                item?.name
              }}</view>
              <view class="textBox" v-html="item?.content"></view>
            </view>
          </view>
        </view>
      </swiper-item>
    </swiper>
    <c_loading v-else></c_loading>
    <hy-comment ref="commentRef" :dynamicId="originList[originIndex]?.id" :userInfo="userInfo" :tableData="commentList"
      :total="commentTotal" @replyFun="replyFun" @update:tableTotal="updateTableTotal" @update:tableData="updateTableData"
      @close="closeComment" />
    <hy-share ref="shareRef" :shareData="shareData" @onShared="onShared" :showReward="hasRewrad"></hy-share>
  </view>
</template>

<script setup lang="ts">
import { ref, reactive, getCurrentInstance, onMounted, computed, watch, nextTick } from 'vue';
import { storeToRefs } from 'pinia'
import { useUserStore, useConfigStore } from '@/store'
import { getImgFullPath, getDistance } from '@/utils/index'
import c_loading from './c_loading.vue'
import c_sidebar from './c_sidebar.vue'
import { enumAll, socialApi, baseApi } from '@/api';
import { route } from '@/utils/common'
import { UserInfo } from '../../store/modules/userStore';
import { sharePathFormat, webSharePathFormat } from '@/common/wechat-share'
import { checkLoginState } from '../../utils/index';
import { onHide } from '@dcloudio/uni-app';


const userStore = useUserStore()
const configStore = useConfigStore()
const { userInfo, hasNewDynamic } = storeToRefs(userStore)
const props = withDefaults(
  defineProps<{
    isPreview?: boolean
    type?: string
    index?: number
  }>(),
  {
    isPreview: false,
    type: 'default'
  }
)
const controls = ref(true)
const fullScreen = ref(false)
interface SwiperItem {
  id: number
  previewImage?: string
  videoUrl?: string
  user: {
    id: number
    nickname: string
    avatar: string
  }
  name: string
  content: string
  contentType: number
  createTime: string
  isPlay: boolean
  favoriteCount: number
  favorited: boolean
  share: number
  focused: boolean
  hot: number
  userId: number
  readCount: number
  status: number
  orientation?: number
}
const originList = ref<SwiperItem[]>([]) // 原始数据
const displaySwiperList = ref<SwiperItem[]>([]) // 用于显示的swiper数据[]
const displayIndex = ref(0) // 用于显示swiper的真正的下标数值只有：0，1，2。
const originIndex = ref(0) // 记录源数据的下标
const current = ref(0)
const oid = ref(0)
const playCount = ref(2) //剩余多少视频加载视频列表
const pageIndex = ref(1)
const pageSize = ref(6)
const finished = ref(false)
const flag = ref(false)
const type = ref('')

async function getDynamicList(dynamicId?: any, isFocused?: boolean) {
  if (dynamicId) {
    const res = await socialApi.dynamicInfo({
      id: dynamicId,
      detail: true
    })
    if (res) {
      const item = res?.data
      item.isPlay = false
      originList.value = []
      originList.value.push(item)
    }
    return
  }
  const { data } = await socialApi.dynamicList({
    pageIndex: pageIndex.value,
    pageSize: pageSize.value,
    type: 3,
    detail: true,
    status: enumAll.audit_status_enum.SUCCESS,
    focused: isFocused || null,
    otherColumns: `favorited,focused,${isFocused ? '' : 'hot'}`,
    sortJson: '[{"column":"createTime","direction":"DESC"}]'
  })
  data.records.forEach((item: SwiperItem) => {
    item.isPlay = false
    originList.value.push(item)
  })
  if (pageIndex.value == 1) {
    initSwiperData(originIndex.value)
  }
  if (data.current < data.pages) {
    pageIndex.value += 1
  } else {
    finished.value = true
  }
}

/**
 * 初始一个显示的swiper数据
 * @originIndex  从源数据的哪个开始显示默认0，如从其他页面跳转进来，要显示第n个，这个参数就是他的下标
 */
function initSwiperData(originIndex: number) {
  if (originIndex < 0 || originIndex >= originList.value.length) {
    originIndex = 0
  }
  const originListLength = originList.value.length // 源数据长度
  const displayList: SwiperItem[] = []
  displayList[displayIndex.value] = originList.value[originIndex]
  displayList[displayIndex.value - 1 == -1 ? 2 : displayIndex.value - 1] =
    originList.value[
    originIndex - 1 == -1 ? originListLength - 1 : originIndex - 1
    ]
  displayList[displayIndex.value + 1 == 3 ? 0 : displayIndex.value + 1] =
    originList.value[originIndex + 1 == originListLength ? 0 : originIndex + 1]
  displaySwiperList.value = displayList

  if (oid.value >= originList.value.length) {
    oid.value = 0
  }
  if (oid.value < 0) {
    oid.value = originList.value.length - 1
  }
  console.log('++++++++++++上一条播放数据 Index:', oid.value)
  uni
    .createVideoContext(
      originList.value[oid.value].id.toString(),
      getCurrentInstance()
    )
    .pause()
  if (!flag.value) {
    flag.value = true
  } else {
    displaySwiperList.value[displayIndex.value].isPlay = true
  }
  setTimeout(() => {
    const video = uni
      .createVideoContext(
        originList.value[originIndex].id.toString(),
        getCurrentInstance()
      )
    try {
      video.play()
      displaySwiperList.value[displayIndex.value].isPlay = true
    } catch (e) {
      console.log('视频播放失败', e)
      displaySwiperList.value[displayIndex.value].isPlay = false
    }
  }, 300)
  var pCount = originList.value.length - playCount.value
  if (originIndex == pCount && !finished.value) {
    getDynamicList()
  }
  const dynamicId = originList.value[originIndex].id
  if (userStore.hasLogin) {
    getCommentList(dynamicId, true)
  }
}

const onPlay = () => {
}
const onPause = () => {
  if (displaySwiperList?.value[displayIndex.value]?.isPlay) {
    displaySwiperList.value[displayIndex.value].isPlay = false
  }
}
const onVideoError = () => {
  console.log('视频播放失败')

  if (displaySwiperList?.value[displayIndex.value]?.isPlay) {
    displaySwiperList.value[displayIndex.value].isPlay = false
  }
}

/**
 * swiper滑动时候
 */
function swiperChange(event: { detail: { current: any } }) {
  const { current } = event.detail
  // =============向后滑动==========
  if (displayIndex.value - current == 2 || displayIndex.value - current == -1) {
    nextFn()
  }
  // ======如果两者的差为-2或者1则是向前滑动============
  else if (
    displayIndex.value - current == -2 ||
    displayIndex.value - current == 1
  ) {
    prevFn()
  }
}
// 切换到上一个视频
function prevFn() {
  const originListLength = originList.value.length // 源数据长度
  originIndex.value =
    originIndex.value - 1 == -1 ? originListLength - 1 : originIndex.value - 1
  displayIndex.value =
    displayIndex.value - 1 == -1 ? 2 : displayIndex.value - 1
  //console.log('---',this.originIndex)
  oid.value = originIndex.value + 1
  initSwiperData(originIndex.value)
}
// 切换到下一个视频
const nextFn = () => {
  const originListLength = originList.value.length // 源数据长度
  originIndex.value =
    originIndex.value + 1 == originListLength ? 0 : originIndex.value + 1
  displayIndex.value =
    displayIndex.value + 1 == 3 ? 0 : displayIndex.value + 1
  oid.value = originIndex.value - 1
  initSwiperData(originIndex.value)
}


// 视频控件
function controlstoggle(e: { detail: { show: boolean } }) {
  controls.value = e.detail.show
}
// 全屏
function fullscreenchangeFn(e: { detail: { fullScreen: boolean } }) {
  fullScreen.value = e.detail.fullScreen
}
// 获取视频宽高
function videoLoaded(e: any, item: SwiperItem) {
  const { width, height } = e.detail
  // console.log('视频宽高', e, e.detail.width, e.detail.height)
  if (width > height) {
    item.orientation = 0
  }
}

function toBusinessCardHome(data: { userId: any }, index: any) {
  if (['preview', 'viewSingleUser'].includes(type.value)) {
    uni.navigateBack()
    return
  }
  route({
    url: `/packageA/pages/businessCard/index`,
    params: {
      userId: data.userId,
      avatar: data?.user?.avatar,
      nickname: data?.user?.nickname
    }
  })
}
// 点击播放
function videoPlay(index: any) {
  const isPlay = displaySwiperList.value[index].isPlay
  const ctx = uni
    .createVideoContext(
      displaySwiperList.value[index].id.toString(),
      getCurrentInstance()
    )
  console.log(`点击${isPlay ? '暂停' : '播放'}`, index)
  try {
    isPlay ? ctx.pause() : ctx.play()
    displaySwiperList.value[index].isPlay = !isPlay
  } catch (e) {
    console.log('视频播放失败', e)
    displaySwiperList.value[index].isPlay = false
  }

}



// 点赞
async function doLike(item: {
  favorited?: boolean
  id: any
  favoriteCount: number
}) {
  if (!userStore.checkLoginState()) return
  const excutor = item.favorited
    ? socialApi.dynamicFavoriteDelete
    : socialApi.dynamicFavoriteAdd
  item.favoriteCount += item.favorited ? -1 : 1
  item.favorited = !item.favorited
  const res = await excutor({
    dynamicId: item.id,
    userId: userInfo.value.id
  })
}

// 关注
async function focusAdd(item: { userId: any; focused: boolean }) {
  if (!userStore.checkLoginState()) return
  const { code } = await socialApi.userFocusAdd({
    targetUserId: item.userId,
    userId: userInfo.value.id
  })
  if (code === 200) {
    item.focused = true
    uni.showToast({
      icon: 'none',
      title: '关注成功'
    })
  }
}

// 评论 
const commentShow = ref(false)
const commentRef = ref()
const commentList = ref<any[]>([])
const commentTotal = ref(0)
function toComment(data: any) {
  console.log('toComment', data)
  if (userStore.checkLoginState()) {
    commentRef.value.open()
    commentShow.value = true
  }
}
function closeComment() {
  commentShow.value = false
}
async function replyFun(params: any, cb: Function) {
  console.log('replyFun', arguments)
  for (let key in params.params) {
    if (params.params[key] === null) {
      delete params.params[key]
    }
  }
  const { data } = await socialApi.dynamicCommentAdd({ ...params.params })
  cb && cb(data)
}
const commentPageObj = reactive({
  pageIndex: 1,
  pageSize: 100,
  finished: false
})
async function getCommentList(dynamicId: number, refresh: boolean = false) {
  if (refresh) {
    commentPageObj.pageIndex = 1
    commentPageObj.finished = false
    commentList.value = []
  }
  if (commentPageObj.finished) return
  const { data } = await socialApi.dynamicCommentListWithChild({
    dynamicId,
    pageIndex: commentPageObj.pageIndex,
    pageSize: commentPageObj.pageSize,
    sortJson: '[{"column":"createTime","direction":"DESC"}]'
  })
  commentList.value.push(...data.records)
  commentTotal.value = data.total
  if (data.current < data.pages) {
    commentPageObj.pageIndex += 1
  } else {
    commentPageObj.finished = true
  }
}
function updateTableData() {
  const dynamicId = displaySwiperList.value[current.value].id
  getCommentList(dynamicId)
}


// 本地更新评论总数
function updateTableTotal(total: number) {
  commentTotal.value = total
}

// 分享
const shareRef = ref()
const hasRewrad = ref(false)
const shareData = ref({})
function setShareData(data: any) {
  shareData.value = {
    title: data.name || data?.user?.nickname || '黑银一码人脉',
    desc: data.content ?? '',
    // #ifdef MP-WEIXIN
    imageUrl: getImgFullPath(data.previewImage),
    path: sharePathFormat({ dynamicId: data.id }),
    // #endif
    // #ifdef H5
    imgUrl: getImgFullPath(data.previewImage),
    link: webSharePathFormat({ dynamicId: data.id })
    // #endif
  }
}
function toShare(data: any) {
  if (!userStore.checkLoginState()) return
  if (data?.user?.forwardDouyinReward) {
    hasRewrad.value = true
  }
  shareRef.value.showPop(data)
  setShareData(data)
}
async function onShared(data: any) {
  if (hasRewrad.value) {
    await socialApi.forwardFinish({
      id: data.dynamicId,
      type: data.type,
    })
  }
}

watch(hasNewDynamic, (n) => {
  if (n) {
    getDynamicList()
  }
})
watch(type, (n) => {
  if (n === 'preview') {
    const video = JSON.parse(uni.getStorageSync('video') || '{}')
    displaySwiperList.value.push(video)
  } else if (n === 'viewSingleUser') {
    const list = JSON.parse(uni.getStorageSync('videoList') || '[]')
    displaySwiperList.value.push(...list)
    current.value = Number(props.index)
  }
})
onMounted(async () => {
  await getDynamicList()
})
defineExpose({
  getDynamicList
})

const isPC = () => {
  const userAgent = navigator.userAgent;
  const screenWidth = window.screen.width;
  const screenHeight = window.screen.height;
  const isDesktopOS = /Windows|Macintosh|Linux/.test(userAgent);
  const isDesktopScreen = screenWidth >= 1024 && screenHeight >= 768;
  return isDesktopOS && isDesktopScreen;
}


// 监听鼠标滚动事件
let lastScrollTime = 0; // 用于记录上一次滚动的时间
const scrollDelay = 300; // 设置滚动切换的延迟时间，毫秒
const handleScroll = (event: { deltaY: number }) => {
  const currentTime = Date.now();
  // 如果两次滚动时间间隔小于 scrollDelay，则忽略
  if (currentTime - lastScrollTime < scrollDelay) {
    return;
  }
  lastScrollTime = currentTime; // 更新滚动时间

  if (event.deltaY > 0) {
    // 向下滚动，切换到下一个视频
    current.value = (current.value + 1) % 3; // 取模切换
    nextFn();
  } else {
    // 向上滚动，切换到上一个视频
    current.value = (current.value - 1 + 3) % 3; // 防止负值并取模
    prevFn();
  }
}

// 初始化监听鼠标滚轮事件
const eventinit = () => {
  if (isPC()) {
    window.addEventListener('wheel', handleScroll);
  }
}
eventinit();

// 兼容移动端浏览器高度自适应
function getWindowConfig() {
  let windowWidth = window.innerWidth;
  let windowHeight = window.innerHeight;
  if (typeof windowWidth !== 'number') {
    if (document.compatMode === 'CSS1Compat') {
      windowWidth = document.documentElement.clientWidth;
      windowHeight = document.documentElement.clientHeight;
    } else {
      windowWidth = document.body.clientWidth;
      windowHeight = window.body.clientHeight;
    }
  }
  return {
    windowWidth: windowWidth,
    windowHeight: windowHeight
  }
}
const swiperHeight = ref('calc(100vh - 102rpx)')
const windowSizeW = ref('100vw')
nextTick(() => {
  const { windowWidth, windowHeight } = getWindowConfig();
  swiperHeight.value = windowHeight - 46 + 'px';
  windowSizeW.value = windowWidth + 'px';
})

onHide(() => {
  try {
    displaySwiperList.value[displayIndex.value].isPlay = false
  } catch {
    console.log('视频播放失败')
  }
})

</script>

<style lang="scss" scoped>
.c_container {
  .swiper {
    width: v-bind(windowSizeW);
    height: v-bind(swiperHeight);
    background-color: #000;

    .videoCore {
      transition: all 0.3s ease-in-out;

      &.foled {
        transform: scale(0.32);
        margin-top: -50%;
      }

      &.noScale {
        transform: scale(1);
      }
    }

    .video {
      width: v-bind(windowSizeW);
      height: calc(100vh - 102rpx);

    }

    .swiperItem {
      .play {
        position: absolute;
        width: 152rpx;
        height: 152rpx;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        margin: auto;
        opacity: 0.6;
        z-index: 2;
      }
    }
  }



  .footer {
    position: absolute;
    width: 100%;
    bottom: 0;
    left: 0;
    z-index: 1;
    box-shadow: 0 80rpx 20rpx rgba(0, 0, 0, 0.08);

    &.showControl {
      bottom: 50rpx;
    }

    .top {
      padding: 0 30rpx 20rpx 30rpx;
      box-sizing: border-box;
      background: linear-gradient(180deg,
          rgba(0, 0, 0, 0) 0%,
          rgba(0, 0, 0, 0.06) 46%,
          rgba(0, 0, 0, 0.08) 100%);

      .labelBox {
        color: #b3b3b3;
        font-size: 24rpx;
      }

      .name {
        color: #ffffff;
        font-size: 30rpx;
        font-weight: bold;
        margin-top: 16rpx;
      }

      .textBox {
        display: flex;
        justify-content: flex-start;
        align-items: center;
        flex-wrap: wrap;
        margin-top: 16rpx;
        color: #ffffff;
        .fn-param {
          font-weight: bold;
        }
        &.tit {
          font-weight: bold;
          font-size: 28rpx;
        }

        .p {
          max-width: 525rpx;
          font-size: 28rpx;
          line-height: normal;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          word-break: break-all;
        }

        .btn {
          color: #ffffff;
          font-size: 26rpx;
          line-height: normal;
        }
      }

      .openBox {
        margin-top: 16rpx;

        .p {
          display: block;
          color: #ffffff;
          font-size: 26rpx;
          line-height: normal;
          word-break: break-all;
          white-space: pre-line;
          word-wrap: break-word;
        }

        .btn {
          color: #ffffff;
          font-size: 26rpx;
          line-height: normal;
          display: block;
          text-align: right;
        }
      }
    }

    .bottom {
      background-color: #fff;
      padding: 20rpx 0;
      display: flex;
      justify-content: space-between;
      align-items: center;

      .left {
        padding-left: 30rpx;
        display: flex;
        justify-content: center;
        align-items: center;

        .pic {
          width: 48rpx;
          height: 48rpx;
          margin-right: 10rpx;
        }

        .num {
          color: #636366;
          font-size: 24rpx;
        }
      }

      .right {
        display: flex;
        justify-content: flex-end;
        align-items: center;
        width: 500rpx;
        box-sizing: border-box;
        padding-right: 30rpx;

        .box {
          position: relative;
          margin-right: 20rpx;
          overflow: visible;

          .btn {
            display: block;
            width: 130rpx;
            height: 100%;
            background-color: rgba(0, 0, 0, 0);
            padding: 0;
            margin: 0;
            text-align: center;
            line-height: normal;

            .pic {
              width: 40rpx;
              height: 40rpx;
              display: inline-block;
              vertical-align: middle;
              position: relative;
              z-index: 2;
              margin-right: 8rpx;
            }

            .text {
              vertical-align: middle;
              display: inline-block;
              color: #636366;
              font-size: 24rpx;
              height: 40rpx;
              line-height: 40rpx;
            }
          }

          .wechat {
            width: 174rpx;

            .pic {
              width: 174rpx;
              height: 56rpx;
            }
          }

          .btn:after {
            border: none;
          }
        }

        .box:last-of-type {
          margin-right: 0;
        }
      }
    }
  }
}
</style>
